<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="app">
      <h2>使用浏览器开发者工具：

        Chrome DevTools 中的 Memory 面板可以用来检测内存泄漏。可以查看 Heap Snapshot 和 Allocation instrumentation on timeline，分析对象分配、释放情况。
        Heap Snapshot：查看对象的分配情况，并通过比较不同时间点的快照来发现泄漏。
        Timeline：在页面交互过程中，查看内存的使用情况，发现持续增长的内存占用。</h2>
      <button id="myButton">按钮</button>
    </div>
    <script>
      /**
       * 内存泄漏的常见情景
       */
      // 1.全局变量：意外的全局变量会导致对象无法被回收
      function test() {
        leakedVar = "This is a global variable"; // 未声明的变量成为全局变量
      }
      test();

      // 2.未移除的事件监听器：
      // 如果事件监听器被绑定在 DOM 元素上，但没有在元素移除后正确移除，可能导致内存泄漏。
      const button = document.getElementById("myButton");
      button.addEventListener("click", function () {
        /* some logic */
        console.log("按钮被点击了");
      });
      // 如果没有 button.removeEventListener，按钮被移除后内存仍未释放

      // 3.闭包（Closures）：
      // 闭包会保持对外部函数变量的引用，如果闭包生命周期过长，会导致外部函数的变量无法释放。
      function createClosure() {
        let largeObject = new Array(1000).fill("Some data");
        return function () {
          console.log(largeObject); // largeObject 被闭包引用，无法被 GC 回收
        };
      }
      let closure = createClosure();

      // 4.DOM 引用：保留对已删除 DOM 元素的引用，导致内存泄漏。
      let div = document.createElement("div");
      document.body.appendChild(div);
      // 如果没有将 div 设置为 null，垃圾回收器可能无法回收它
      div = null;

      // 5.定时器（setInterval/setTimeout）未清除：
      let interval = setInterval(function () {
        console.log("Running");
      }, 1000);
      // 如果没有 clearInterval(interval)，定时器将一直运行，导致内存泄漏

      // 6.Web Workers 和后台线程：如果 Web Worker 或后台线程没有正确终止，可能会导致内存泄漏。
      // const worker = new Worker("worker.js");
      // 如果没有 worker.terminate()，worker 可能导致内存泄漏


    </script>
  </body>
</html>
